#ifndef SRC_GETOPT_H_
#define SRC_GETOPT_H_

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

#include "src/lterr.h"

/** 在每个参数调用，当name为0时，value是位置参数，否则是选项。

ctx在ltopt_Parse中传入。
*/
typedef lterr_Code (*ltopt_OnArgument)(void* ctx, char name, char const* value);

/** 解析命令行参数。

- 如果选项是take_opts字符串中的字符，那么选项则需要参数，否则不需要参数。
- 在解析到参数时调用on_argument，ctx会传入on_argument。

成功时返回0，如果on_argument返回非0，会结束解析立刻返回。

命令行参数分为位置参数和选项。选项名是减号（-）后跟一个非0而且非减号（-）的字母。

选项分为带参数和不带参数的。不带参数的选项可以组合在一起。例如 -abc，表示
-a，-b和-c。

带参数的选项可以将参数跟选项名放在一起，也可以放在后面。例如：

  -oout.txt
  -o out.txt

注意单纯的-abc是存在歧义的，它可以表示3个不带参数的选项，也可以表示-a有bc作为
选项参数，因此ltopt_Parse需要输入来明确每个选项是否带参数。

对于一个选项，例如-abc，如果-a是不带参数的，那么-b和-c也必须是不带参数的。否则
会报告ltopt_kInvalidFold。
*/
lterr_Code ltopt_Parse(int argc, char const* argv[], char const* take_opts,
                       ltopt_OnArgument on_argument, void* ctx);

/**命令行选项的帮助。*/
typedef struct {
    char name;
    char const* help;
} ltopt_OptionHelp;

/**命令行位置参数的帮助。*/
typedef struct {
    char const* name;
    char const* help;
    bool multiple;
} ltopt_ArgumentHelp;

/**命令行参数的帮助。*/
typedef struct {
    char const* name;
    char const* help;

    ltopt_OptionHelp const* options;
    ltopt_ArgumentHelp const* arguments;
} ltopt_Usage;

void ltopt_WriteUsage(ltopt_Usage* usage, FILE* fp);

#endif // SRC_GETOPT_H_
